import base64
import hashlib
from datetime import datetime, timedelta

from captcha.views import CaptchaStore, captcha_image
from django.contrib import auth
from django.contrib.auth import login
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import serializers
from rest_framework.status import HTTP_401_UNAUTHORIZED
from rest_framework.views import APIView
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.token_blacklist.models import OutstandingToken
from rest_framework_simplejwt.tokens import RefreshToken, AccessToken
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

from django.conf import settings

from application import dispatch
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.request_util import save_login_log
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomValidationError
import requests
from django_redis import get_redis_connection
import json


class CaptchaView(APIView):
    authentication_classes = []
    permission_classes = []

    @swagger_auto_schema(
        responses={"200": openapi.Response("获取成功")},
        security=[],
        operation_id="captcha-get",
        operation_description="验证码获取",
    )
    def get(self, request):
        data = {}
        if dispatch.get_system_config_values("base.captcha_state"):
            hashkey = CaptchaStore.generate_key()
            id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
            imgage = captcha_image(request, hashkey)
            # 将图片转换为base64
            image_base = base64.b64encode(imgage.content)
            data = {
                "key": id,
                "image_base": "data:image/png;base64," + image_base.decode("utf-8"),
            }
        return DetailResponse(data=data)


class LoginSerializer(TokenObtainPairSerializer):
    """
    登录的序列化器:
    重写djangorestframework-simplejwt的序列化器
    """
    captcha = serializers.CharField(
        max_length=6, required=False, allow_null=True, allow_blank=True
    )

    class Meta:
        model = Users
        fields = "__all__"
        read_only_fields = ["id"]

    default_error_messages = {"no_active_account": _("账号/密码错误")}

    def validate(self, attrs):

        captcha = self.initial_data.get("captcha", None)
        if dispatch.get_system_config_values("base.captcha_state"):
            if captcha is None:
                raise CustomValidationError("验证码不能为空")
            self.image_code = CaptchaStore.objects.filter(
                id=self.initial_data["captchaKey"]
            ).first()
            five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
            if self.image_code and five_minute_ago > self.image_code.expiration:
                self.image_code and self.image_code.delete()
                raise CustomValidationError("验证码过期")
            else:
                if self.image_code and (
                        self.image_code.response == captcha
                        or self.image_code.challenge == captcha
                ):
                    self.image_code and self.image_code.delete()
                else:
                    self.image_code and self.image_code.delete()
                    raise CustomValidationError("图片验证码错误")

        payload = {'username': attrs["username"], 'password': attrs["password"]}
        headers = {
            "Content-Type": "application/json"
        }

        data = {}
        # 隔離超級管理員登錄
        if attrs["username"] == "admin" and attrs["password"] == "admin123456":
            now = datetime.now()
            formatted_now = now.strftime('%Y-%m-%d %H:%M:%S')
            md = hashlib.md5()  # 创建md5对象
            md.update(f"ACCESS_TOKEN_{formatted_now}_ZBY1988".encode())  # 生成加密字符
            access_token = md.hexdigest()  # 返回的是加密后的字符

            rep_data = {
                "data":{
                    "access_token":access_token,
                    "refresh_token":"ACCESS_TOKEN20250312REFRESH"
                }
            }
            data['isadmin'] = 1  # 是否超级管理员

            redis_conn = get_redis_connection()
            redis_conn.set(f"admin_login_token:{rep_data['data']['access_token']}", json.dumps(
                {"username": attrs['username'], "refresh_token": rep_data["data"]['refresh_token']}),
                           ex=60 * 60 * 24 * 7)
        else:
            data['isadmin'] = 0  # 是否超级管理员
            response = requests.post('https://10.80.40.22:8443/wsweblogin', json=payload, headers=headers, verify=False)
            rep_data = response.json()


            if rep_data["code"] == 400:
                return {"code": 4000, "msg": "用户名/密码不正确"}

            redis_conn = get_redis_connection()
            redis_conn.set(f"login_token:{rep_data['data']['access_token']}", json.dumps(
                {"username": attrs['username'], "refresh_token": rep_data["data"]['refresh_token']}),
                           ex=60 * 60 * 24)

        # request = self.context.get("request")
        # request.session['jwt_token'] = rep_data["data"]["access_token"]
        # request.session['username'] = attrs["username"]
        # request.session['password'] = attrs["password"]

        # print(request.session['jwt_token'])




        data["name"] = attrs["username"]
        data["userId"] = 0
        data["avatar"] = ""
        data['user_type'] = 0
        data['access'] = rep_data["data"]["access_token"]
        data['refresh'] = rep_data["data"]["refresh_token"]


        dept = None
        # dept = getattr(self.user, 'dept', None)
        # if dept:
        #     data['dept_info'] = {
        #         'dept_id': dept.id,
        #         'dept_name': dept.name,
        #
        #     }
        # role = getattr(self.user, 'role', None)
        # if role:
        #     data['role_info'] = role.values('id', 'name', 'key')

        # request.user = self.user
        # 记录登录日志
        # save_login_log(request=request)
        # 是否开启单点登录
        # if dispatch.get_system_config_values("base.single_login"):
        #     # 将之前登录用户的token加入黑名单
        #     user = Users.objects.filter(id=self.user.id).values('last_token').first()
        #     last_token = user.get('last_token')
        #     if last_token:
        #         try:
        #             token = RefreshToken(last_token)
        #             token.blacklist()
        #         except:
        #             pass
        #     # 将最新的token保存到用户表
        #     Users.objects.filter(id=self.user.id).update(last_token=data.get('refresh'))
        return {"code": 2000, "msg": "请求成功", "data": data}


class CustomTokenRefreshView(APIView):
    authentication_classes = []
    permission_classes = []
    """
    自定义token刷新
    """

    def post(self, request, *args, **kwargs):
        refresh_token = request.data.get("refresh")
        token = request.data.get("token")

        payload = {}
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {refresh_token}"
        }
        response = requests.get('https://10.80.40.22:8443/refreshtoken', params=payload,
                                headers=headers, verify=False)
        rep_data = response.json()
        if rep_data["code"] == 401:
            return ErrorResponse(code=4001, msg="登录失败")

        redis_conn = get_redis_connection()
        username_obj = redis_conn.get(f"login_token:{token}")

        if not username_obj:
            return ErrorResponse(code=4001, msg="登录失败")
        username_obj = json.loads(username_obj.decode())

        redis_conn.set(f"login_token:{rep_data['data']['access_token']}",
                       json.dumps({"username": username_obj['username'], "refresh_token": rep_data["data"]['refresh_token']}),
                       ex=60 * 60 * 24)

        data = {
            "access": str(rep_data["data"]["access_token"]),
            "refresh": str(rep_data["data"]["refresh_token"])
        }

        return DetailResponse(data=data)


class LoginView(TokenObtainPairView):
    """
    登录接口
    """
    serializer_class = LoginSerializer
    permission_classes = []


class LoginTokenSerializer(TokenObtainPairSerializer):
    """
    登录的序列化器:
    """

    class Meta:
        model = Users
        fields = "__all__"
        read_only_fields = ["id"]

    default_error_messages = {"no_active_account": _("账号/密码不正确")}

    def validate(self, attrs):
        if not getattr(settings, "LOGIN_NO_CAPTCHA_AUTH", False):
            return {"code": 4000, "msg": "该接口暂未开通!", "data": None}
        data = super().validate(attrs)
        data["name"] = self.user.name
        data["userId"] = self.user.id
        return {"code": 2000, "msg": "请求成功", "data": data}


class LoginTokenView(TokenObtainPairView):
    """
    登录获取token接口
    """

    serializer_class = LoginTokenSerializer
    permission_classes = []


class LogoutView(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self, request):
        refresh_token = request.data.get("refresh")
        token = request.data.get("token")

        redis_conn = get_redis_connection()

        redis_conn.delete(f"login_token:{token}")


        return DetailResponse(msg="注销成功")


class ApiLoginSerializer(CustomModelSerializer):
    """接口文档登录-序列化器"""

    username = serializers.CharField()
    password = serializers.CharField()

    class Meta:
        model = Users
        fields = ["username", "password"]


class ApiLogin(APIView):
    """接口文档的登录接口"""

    serializer_class = ApiLoginSerializer
    authentication_classes = []
    permission_classes = []

    def post(self, request):
        username = request.data.get("username")
        password = request.data.get("password")
        user_obj = auth.authenticate(
            request,
            username=username,
            password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
        )
        if user_obj:
            login(request, user_obj)
            return redirect("/")
        else:
            return ErrorResponse(msg="账号/密码错误")
